<?php

namespace App\Repository;

use App\Models\Order;
use App\Models\OrderProduct;
use App\Models\Product;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Class OrderRepository
 * @package App\Repository
 */
class OrderRepository
{
    /** @var */
    public $orderProduct;
    /**
     * 客户端传递的商品列表参数[订单商品列表]
     * @var
     */
    protected $oproducts;
    /**
     * 数据库查询中真事的商品信息(包括库存量)
     * [用来对比客户端传递的商品列表]
     * @var
     */
    protected $products;
    /**
     * 用户ID
     * @var
     */
    protected $uid;

    /**
     * 下单[检测库存量，如果通过则增加一条订单信息，返回订单ID。否则返回订单失败信息]
     * @param $uid
     * @param $oproducts
     * @return array
     */
    public function place($uid, $oproducts)
    {
        //products[数据库中的商品信息]和oproducts做对比检测库存量
        $this->uid = $uid;
        $this->oproducts = $oproducts;
        $this->products = $this->getProductsByOrder($oproducts);
        $status = $this->getOrderStatus();
        //检测库存量没有通过
        if (!$status['pass']){
            $status['order_id'] = -1; //和成功返回信息一致
            return $status;
        }
        //创建订单
        $orderSnap = $this->snapOrder($status);
        $order = $this->createOrder($orderSnap);
        $order['pass'] = true;

        return $order;
    }

    /**
     * 获取订单状态
     * @return array
     */
    private function getOrderStatus()
    {
        //订单的属性状态
        $status = [
            'pass' => true,        //库存量检测是否通过
            'orderPrice' => 0,     //订单中所有商品的总价格
            'totalCount' => 0,     //商品总数量
            'pStatusArray' => [],  //保存订单中所有商品中的详细信息
        ];

        foreach ($this->oproducts as $oproduct) {
            $pStatus = $this->getProductStatus($oproduct['product_id'], $oproduct['count'],$this->products);
            if (!$pStatus['haveStock']){
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['totalCount'] += $pStatus['count'];
            array_push($status['pStatusArray'], $pStatus);
        }
        return $status;
    }


    /**
     * 检测库存量对外方法
     * @param $orderId
     * @return array
     */
    public function checkOrderStock($orderId)
    {
        $oproducts = OrderProduct::where('order_id', $orderId)->get();

        $this->oproducts = $oproducts;
        $this->products = $this->getProductsByOrder($oproducts);

        return $this->getOrderStatus();
    }
    /**
     * 查询商品的状态
     * @param $oPId 订单中的商品的ID
     * @param $oCount 订单中的购买商品的数量
     * @param $products 真实数据库中的商品
     * @return array  返回商品的状态
     */
    private function getProductStatus($oPId, $oCount, $products) {
        //获取订单中某类商品的下标
        $pIndex = -1;
        //保存订单下的某一个商品信息[用于历史订单]
        $pStatus = [
                'id' => null,
                'haveStock' => false,//当前是否有库存量
                'count' => 0,        //当前订单请求的商品的数量
                'name' => '',        //name
                'totalPrice' => 0,   //订单中某类商品的总价格
        ];
        for ($i = 0; $i < count($products); $i++) {
            if ($oPId == $products[$i]['id']) {
                $pIndex = $i;
            }
        }
        //客户端传递的product_id如果不存在
        if ($pIndex == -1) {
            throw new NotFoundHttpException('id为' . $oPId . '的商品不存在,创建订单失败', null, 80000);
        } else {
            $product = $products[$pIndex];
            $pStatus['id'] = $product['id'];
            $pStatus['name'] = $product['name'];
            $pStatus['count'] = $oCount;
            $pStatus['totalPrice'] = $product['price'] * $oCount;

            if ($product['stock'] - $oCount >= 0) {
                $pStatus['haveStock'] = true;
            }
        }
        return $pStatus;
    }
    /**
     * 根据订单信息查询真实商品信息
     * @param $oproducts
     * @return array
     */
    private function getProductsByOrder($oproducts)
    {
        $oproductsIds = [];
        foreach ($oproducts as $oproduct) {
            array_push($oproductsIds, $oproduct['product_id']);
        }

        $products = Product::whereIn('id', $oproductsIds)
                ->get(['id', 'name', 'price', 'stock', 'main_img_url'])
                ->toArray();
        return $products;
    }

    /**
     * 获取用户的收货地址
     * @return \Illuminate\Database\Eloquent\Model|null|static
     */
    public function getUserAddress()
    {
        $userAddress = UserAddressRepository::getUserAddressByUserId($this->uid);
        if (!$userAddress){
            throw new NotFoundHttpException('用户收货地址不存在，下单失败', null, 60001);
        }
        return ($userAddress);
    }
    /**
     * 生成订单快照
     * @param $status
     */
    private function snapOrder($status)
    {
        $snap = [
                'orderPrice' => 0,
                'totalCount' => 0, // 商品的总数量
                'pStatus' => [],
                'snapAddress' => null,
                'snapName' => '',  //历史订单的订单概要
                'snapImg' => ''    //历史订单的订单图片
        ];
        $snap['orderPrice'] = $status['orderPrice'];
        $snap['totalCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        $snap['snapAddress'] = json_encode($this->getUserAddress());
        $snap['snapName'] = $this->products[0]['name'];
        $snap['snapImg'] = $this->products[0]['main_img_url'];
        if (count($this->products) > 1){
            $snap['snapName'] .= '等';
        }
        return $snap;
    }

    /**
     * 将订单信息新增到数据库中  主表和order_products表
     * @param $snap
     * @return array
     * @throws \Exception
     */
    private function createOrder($snap)
    {
        $order = new Order();
        try {
            \DB::beginTransaction();
            $orderNo = self::makeOrderNo();
            $order->user_id = $this->uid;
            $order->order_no = $orderNo;
            $order->status = 1;
            $order->prepay_id = 1;
            $order->snap_img = $snap['snapImg'];
            $order->snap_name = $snap['snapName'];
            $order->total_count = $snap['totalCount'];
            $order->total_price = $snap['orderPrice'];
            $order->snap_address = $snap['snapAddress'];
            $order->snap_items = json_encode($snap['pStatus']);

            $order->save();

            $orderId = $order->id;
            foreach ($this->oproducts as &$oproduct) {
                $oproduct['order_id'] = $orderId;
            }
            $orderProduct = new OrderProduct();
            $orderProduct->insert($this->oproducts);

            \DB::commit();
            return ['order_no' => $orderNo, 'order_id' => $orderId, 'created_at' => $order->created_at];
        }catch (\Exception $exception){
            \DB::rollBack();
            throw $exception;
        }
    }
    /**
     * 生成订单号
     * @return string
     */
    public static function makeOrderNo()
    {
        $yCode = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
        $orderSn =
                $yCode[intval(date('Y') - 2017)]
                . strtoupper(dechex(date('m')))
                . date('d')
                . substr(time(), -5)
                . substr(microtime(), 2, 5)
                . sprintf('%02d', rand(0, 99));
        return $orderSn;
    }

    /**
     * 根据ID查询订单信息
     * @param $id
     * @return \Illuminate\Database\Eloquent\Model|null|static
     */
    public function getOrderById($id)
    {
        return Order::where('id', $id)->first();
    }

    /**
     * 根据ID更新数据
     * @param $id
     * @param $data
     * @return bool
     */
    public function updateDataById($id, $data)
    {
        return Order::where('id', $id)->update($data);
    }

    /**
     * 根据订单号查询订单数据
     * @param $orderNo
     * @return mixed
     */
    public static function getDataByOrderNo($orderNo)
    {
        return Order::where('order_no', $orderNo)->lock(true)->first();
    }

    /**
     * 更新订单状态
     * @param $id
     * @param $status
     * @return bool
     */
    public static function updateOrderStatusById($id, $status)
    {
        return Order::where('id', $id)->update(['status'=> $status] );
    }



}